package com.example.demo.lambda;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.RandomUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.*;

/**
 * @Author xiao
 * @Date 2025/5/2 上午 10:48
 * @ClassName: OrdersDemo
 * @Desc:
 */
public class OrdersDemo {


    public static void main(String[] args) {
        //String time = "2025-05-02T17:31:14.452146200";
        //System.out.println(DateUtil.format(LocalDateTime.parse(time), "yyyy-MM-hh"));
        //String timeFormat = LocalDateTime.parse(time).format(DateTimeFormatter.ofPattern("yyyy-MM-dd mm:ss"));
        //System.out.println(timeFormat);

        //writeFile();
        //f2();
        f4();
        f5();
    }

    public static void writeFile() {
        try (OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("order.txt"))) {
            for (int i = 0; i < 1000000; i++) {
                LocalDateTime date = LocalDateTime.now().minusMonths(RandomUtil.randomInt(12));
                double price = RandomUtil.randomDouble(9, 1, RoundingMode.HALF_UP);
                int num = RandomUtil.randomInt(1, 3);
                double totalPrice = price * num;
                String[] addrs = new String[]{"北京", "上海", "广州", "深圳"};
                MyOrder m = new MyOrder(
                        date,
                        IdUtil.simpleUUID(),
                        "goods:" + RandomUtil.randomInt(1, 10000),
                        String.valueOf(10000000 + RandomUtil.randomInt(100)),
                        price,
                        num,
                        totalPrice,
                        addrs[RandomUtil.randomInt(4)]
                );
                System.out.println(m.toString());
                osw.write(m.toString());
                osw.write("\r\n");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public static void f() {
        // 统计销量前10的商品
        try {
            Map<String, Long> collect = Files.lines(Paths.get(("order.txt")))
                    .map(f -> f.split(","))
                    .collect(groupingBy(array -> array[OrderFieldEnum.goodsId.getField()], counting()));
            collect.entrySet().stream()
                    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                    .limit(10)
                    .forEach(System.out::println);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void f2() {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM");
        //    统计每个月销量
        try (Stream<String> stream = Files.lines(Paths.get("order.txt"))) {
            stream.map(s -> s.split(","))
                    .map(array -> LocalDateTime.parse(array[OrderFieldEnum.date.getField()]).format(format))
                    .collect(groupingBy(c -> c, counting()))
                    .forEach((k, v) -> {
                        System.out.println(k + " 订单数 " + v);
                    });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void f3() {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM");
        //    统计销量最高的月份
        try (Stream<String> stream = Files.lines(Paths.get("order.txt"))) {
            Optional<Map.Entry<String, Long>> max = stream.map(s -> s.split(","))
                    .collect(groupingBy(array -> LocalDateTime.parse(array[OrderFieldEnum.date.getField()]).format(format), counting()))
                    .entrySet().stream()
                    //.max(Comparator.comparingLong(Map.Entry::getValue));
                    .max(Comparator.comparingLong(entry -> entry.getValue()));
            max.ifPresent(System.out::println);

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 统计每个地区下单最多的用户
    public static void f4() {
        try (Stream<String> stream = Files.lines(Paths.get("order.txt"))) {
            Map<String, Map<String, Long>> collect = stream.map(s -> s.split(","))
                    .collect(groupingBy(array -> array[OrderFieldEnum.addr.getField()],
                            groupingBy(array -> array[OrderFieldEnum.userId.getField()], counting())));
            Map<String, Map.Entry<String, Long>> entryMap2 = collect.entrySet().stream()
                    .map(entry -> Map.entry( //Map.entry是创建一个Entry对象
                            entry.getKey(), // key使用原有key
                            entry.getValue().entrySet().stream()
                                    .max(Map.Entry.comparingByValue()) // value转为流后找到最大值
                                    .orElse(Map.entry("-1",0L))
                    ))
                    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
            entryMap2.entrySet().forEach(
                    System.out::println
            );

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
    // 每个地区前三
    public static void f5() {
        try (Stream<String> stream = Files.lines(Paths.get("order.txt"))) {
            Map<String, Map<String, Long>> collect = stream.map(s -> s.split(","))
                    .collect(groupingBy(array -> array[OrderFieldEnum.addr.getField()],
                            groupingBy(array -> array[OrderFieldEnum.userId.getField()], counting())));
            Map<String, List<Map.Entry<String, Long>>> listMap = collect.entrySet().stream()
                    .map(entry -> Map.entry( //Map.entry是创建一个Entry对象
                            // key使用原有key
                            entry.getKey(),
                            // value转为流后找到最大值
                            entry.getValue().entrySet().stream()
                                    .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                                    .limit(3)
                                    .collect(toList())
                    ))
                    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
            listMap.entrySet().forEach(
                    System.out::println
            );

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class MyOrder implements Serializable {
        private LocalDateTime date;
        private String orderId;
        private String goodsId;
        private String userId;
        private double price;
        private Integer num;
        private double totalPrice;
        private String addr;

        @Override
        public String toString() {
            return date + "," + orderId + "," + goodsId + "," + userId + "," + price + "," + num + "," + totalPrice + "," + addr;
        }
    }
}
